package com.sicau.smarttraceplatform.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sicau.smarttraceplatform.common.aop.ValidateAspect;
import com.sicau.smarttraceplatform.common.returning.ResultData;
import com.sicau.smarttraceplatform.entity.Area;
import com.sicau.smarttraceplatform.entity.Trace;
import com.sicau.smarttraceplatform.entity.User;
import com.sicau.smarttraceplatform.entity.param.area.AreaAddParam;
import com.sicau.smarttraceplatform.entity.param.area.AreaUpdateParam;
import com.sicau.smarttraceplatform.entity.param.trace.TraceAddParam;
import com.sicau.smarttraceplatform.entity.param.trace.TraceQueryParam;
import com.sicau.smarttraceplatform.entity.param.trace.TraceUpdateParam;
import com.sicau.smarttraceplatform.entity.vo.PageDataVO;
import com.sicau.smarttraceplatform.entity.vo.trace.TraceInfoVO;
import com.sicau.smarttraceplatform.service.AreaService;
import com.sicau.smarttraceplatform.service.TraceService;
import com.sicau.smarttraceplatform.utils.AliOSSUtil;
import com.sicau.smarttraceplatform.utils.UUIDUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.dozer.Mapper;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

import static com.sicau.smarttraceplatform.common.constants.CommonURLConstants.TRACE_PREFIX;
import static com.sicau.smarttraceplatform.common.constants.commonConstants.CURRENT_USER;

/**
 * <p>
 * 耕种管收数据 前端控制器
 * </p>
 *
 * @author sxt && ttxxi
 * @since 2020-05-24
 */
@RestController
@RequestMapping(TRACE_PREFIX)
@Slf4j
@Api(tags = "耕种管收数据")
public class TraceController {

    @Resource
    private Mapper dozerMapper;
    @Resource
    private AreaService areaService;
    @Resource
    private TraceService traceService;

    @SuppressWarnings("unused")
    @PostMapping
    @ApiOperation(value = "新增耕种管收数据记录")
    @ValidateAspect.ParamValidate()
    public ResultData<Boolean> addTraceInfo(@ApiParam(hidden = true) HttpServletRequest request,
                                            @Valid TraceAddParam traceAddParam,
                                            @Valid AreaAddParam areaAddParam,
                                            @ApiParam(hidden = true) BindingResult bindingResult) {

        User user = (User) request.getSession().getAttribute(CURRENT_USER);

        //先插入area
        Area area = dozerMapper.map(areaAddParam, Area.class)
                .setCreated(LocalDateTime.now())
                .setCreator(user != null ? user.getId().toString() : null);
        boolean rs1 = areaService.save(area);
        Integer areaId = areaService.queryByEntity(area).getId();

        //再插入trace，因为trace依赖area的id
        Trace trace = new Trace();
        BeanUtils.copyProperties(traceAddParam, trace);
        trace.setCreator(user != null ? user.getId().toString() : null)
                .setAreaId(areaId)
                .setCreated(LocalDateTime.now())
                .setTraceId(UUIDUtils.getTimeCode());
        log.info("新增耕种管收数据记录操作, 溯源信息: {}", trace);

        //添加操作
        boolean rs2 = traceService.save(trace);

        //结果返回
        if (rs1 && rs2) {
            log.info("耕种管收数据添加成功");
            return new ResultData<Boolean>()
                    .OK()
                    .setResultIns("耕种管收数据添加成功")
                    .setObj(Boolean.TRUE);
        } else {
            log.info("耕种管收数据添加失败");
            return new ResultData<Boolean>()
                    .FAILED()
                    .setResultIns("耕种管收数据添加失败")
                    .setObj(Boolean.FALSE);
        }

    }


    @GetMapping
    @ApiOperation(value = "查询耕种管收数据记录(传入条件则根据条件查询, 否则查询全部数据)")
    public ResultData<PageDataVO<TraceInfoVO>> getTraceInfo(TraceQueryParam queryParam) {
        log.info("查询耕种管收数据记录");
        return new ResultData<PageDataVO<TraceInfoVO>>().OK().setObj(traceService.queryTraceInfoByCondition(queryParam));
    }

    @DeleteMapping
    @ApiOperation(value = "根据id删除耕种管收数据记录")
    public ResultData<Boolean> removeTraceInfo(@RequestParam Integer id) {
        log.info("根据id删除耕种管收数据记录, id: {}", id);
        Trace trace = traceService.getById(id);
        log.info("删除trace对应的areaId【{}】的数据",trace.getAreaId());
        boolean rs1 = areaService.removeById(trace.getAreaId());
        boolean rs2 = traceService.removeById(id);
        boolean rs = rs1 && rs2;
        log.info("删除结果: {}", rs ? "删除成功" : "删除失败");
        return new ResultData<Boolean>().OK().setObj(rs).setResultIns(rs ? "删除成功" : "删除失败, 或者该条记录是否已经被删除?");
    }


    @PutMapping
    @ApiOperation(value = "修改耕种管收数据记录")
    @ValidateAspect.ParamValidate()
    public ResultData<Boolean> updateTraceInfo(@ApiParam(hidden = true) HttpServletRequest request,
                                               @Valid TraceUpdateParam traceUpdateParam,
                                               @Valid AreaUpdateParam areaUpdateParam,
                                               @SuppressWarnings("unused") @ApiParam(hidden = true) BindingResult bindingResult) {

        //数据整理
        Trace trace = new Trace();
        BeanUtils.copyProperties(traceUpdateParam, trace);
        User user = (User) request.getSession().getAttribute(CURRENT_USER);
        trace.setMender(user != null ? user.getId().toString() : null)
                .setModified(LocalDateTime.now());
        log.info("修改耕种管收数据记录操作, 溯源信息: {}", trace);

        //更新操作
        boolean rs1 = traceService.updateById(trace);

        //更新地区信息
        Area area = dozerMapper.map(areaUpdateParam, Area.class)
                .setMender(user!=null?user.getId().toString():"")
                .setModified(LocalDateTime.now());
        log.info("修改耕地区信息操作, 溯源信息: {}", area);
        boolean rs2 = areaService.updateById(area);

        //结果返回
        if (rs1 && rs2) {
            log.info("耕种管收数据修改成功");
            return new ResultData<Boolean>()
                    .OK()
                    .setResultIns("耕种管收数据修改成功")
                    .setObj(Boolean.TRUE);
        } else {
            log.info("耕种管收数据修改失败");
            return new ResultData<Boolean>()
                    .FAILED()
                    .setResultIns("耕种管收数据修改失败")
                    .setObj(Boolean.FALSE);
        }

    }

    /**
     * 图片地址前缀
     */
    private static final String IMAGE_PREFIX = "https://smart-trace.oss-cn-hangzhou.aliyuncs.com/";

    @PostMapping("/picture")
    @ApiOperation(value = "上传耕种管收数据的图片", notes = "上传耕种管收数据的图片")
    @ApiImplicitParam(name = "traceId", value = "溯源id", required = true)
    public ResultData uploadTraceImage(@ApiParam(name = "file", value = "图片", required = true)MultipartFile file, String traceId){
        if (StringUtils.isEmpty(traceId) || file==null){
            return new ResultData().FAILED().setResultIns("参数不全");
        }
        Trace trace = traceService.getOne(new LambdaQueryWrapper<Trace>().eq(Trace::getTraceId, traceId));
        if (trace==null){
            return new ResultData().FAILED().setResultIns("traceId错误");
        }
        if (!StringUtils.isEmpty(trace.getImage())){
            AliOSSUtil.deleteObject(trace.getImage());
        }
        String oldName = file.getOriginalFilename();
        int randomNum= (int)(new Random().nextDouble()*(99999-10000 + 1))+ 10000;
        String newName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+randomNum+oldName.substring(oldName.indexOf("."));
        AliOSSUtil.uploadObject(file, traceId+"/"+newName);
        trace.setImage(IMAGE_PREFIX+traceId+"/"+newName);
        traceService.updateById(trace);
        return new ResultData().OK();
    }

    @DeleteMapping("/picture")
    @ApiOperation(value = "删除耕种管收数据的图片", notes = "删除耕种管收数据的图片")
    @ApiImplicitParam(name = "traceId", value = "溯源id", required = true)
    public ResultData uploadTraceImage(String traceId){

        Trace trace = traceService.getOne(new LambdaQueryWrapper<Trace>().eq(Trace::getTraceId, traceId));
        if (trace==null){
            return new ResultData().FAILED().setResultIns("traceId错误");
        }
        if (!StringUtils.isEmpty(trace.getImage())){
            AliOSSUtil.deleteObject(trace.getImage());
            trace.setImage("");
            traceService.updateById(trace);
        }
        return new ResultData().OK();
    }

    @GetMapping("/allTraceId")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @ApiOperation(value = "查询所有溯源id", notes = "查询所有溯源id")
    public ResultData<List<String>> getAllTraceId() {
        List<Trace> list = traceService.list();
        return new ResultData<List<String>>().OK().setObj(list.stream().map(Trace::getTraceId).collect(Collectors.toList()));
    }


}

